package com.ics.cmsadmin.modules.pub.service;

import com.aliyun.oss.ServiceException;
import com.ics.cmsadmin.frame.core.enums.ApiResultEnum;
import com.ics.cmsadmin.frame.property.WechatConfig;
import com.ics.cmsadmin.modules.pub.dao.WeChatSessionMapper;
import com.ics.cmsadmin.frame.core.exception.CmsException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;

@Service
public class WeChatAuthService {
    private Logger logger = LoggerFactory.getLogger(WeChatAuthService.class);

    private RestTemplate restTemplate;

    @Autowired
    private WeChatSessionMapper weChatSessionMapper;

    @Autowired
    private WechatConfig wechatConfig;


    //请求此地址即跳转到二维码登录界面
    private static final String AUTHORIZATION_URL =
            "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";

    // 获取用户 openid 和access——toke 的 URL
    private static final String ACCESSTOKE_OPENID_URL =
            "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

    private static final String REFRESH_TOKEN_URL =
            "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";

    private static final String USER_INFO_URL =
            "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";

    private static final String SCOPE = "snsapi_userinfo";

    private String callbackUrl = "http://isand.mynatapp.cc/ics/api/students/wechat"; //回调域名

    public String getAuthorizationUrl() throws UnsupportedEncodingException {
        callbackUrl = URLEncoder.encode(callbackUrl, "utf-8");
        String url = String.format(AUTHORIZATION_URL, wechatConfig.appId, callbackUrl, SCOPE, System.currentTimeMillis());
        return url;
    }


    public JSONObject getAccessToken(String code) throws CmsException{
        String url = String.format(ACCESSTOKE_OPENID_URL, wechatConfig.appId, wechatConfig.appSecret, code);
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
        URI uri = builder.build().encode().toUri();

        String resp = getRestTemplate().getForObject(uri, String.class);
        logger.error("getAccessToken resp = " + resp);
        if (resp.contains("openid")) {
            JSONObject jsonObject = JSONObject.fromObject(resp);
            String access_token = jsonObject.getString("access_token");
            String openId = jsonObject.getString("openid");
            String unionid = jsonObject.getString("unionid");
            String refreshToken = jsonObject.getString("refresh_token");
            Integer expiresIn = Integer.valueOf(jsonObject.getString("expires_in"));

            JSONObject res = new JSONObject();
            res.put("access_token", access_token);
            res.put("openId", openId);
            res.put("refresh_token", refreshToken);
            res.put("unionId", unionid);
            return res;
        } else {
            throw new ServiceException("获取token失败，msg = " + resp);
        }
    }

    private RestTemplate getRestTemplate() {
        if (this.restTemplate == null) {
            this.restTemplate = new RestTemplate();
        }
        return this.restTemplate;
    }

    public Boolean checkAccessToken(String openId, String accessToken){
        return accessToken.equals(weChatSessionMapper.select(openId).getAccessToken());
    }

    public JSONObject getUserInfo(String accessToken, String openId) throws CmsException{
        String url = String.format(USER_INFO_URL, accessToken, openId);
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
        URI uri = builder.build().encode().toUri();

        String resp = getRestTemplate().getForObject(uri, String.class);
        logger.error("getUserInfo resp = " + resp);
        if (resp.contains("errcode")) {
            throw new ServiceException("获取用户信息错误，msg = " + resp);
        } else {
            try {
                resp = new String(resp.getBytes("ISO-8859-1"), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new CmsException(ApiResultEnum.CHARSET_CONVERT_FAILED);
            }
            JSONObject data = JSONObject.fromObject(resp);
            return data;
        }
    }

    //微信的token只有2小时的有效期，过时需要重新获取，所以官方提供了
    //根据refresh_token 刷新获取token的方法，本项目仅仅是获取用户
    //信息，并将信息存入库，所以两个小时也已经足够了
    public String refreshToken(String refresh_token) {

        String url = String.format(REFRESH_TOKEN_URL, wechatConfig.appId, refresh_token);

        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
        URI uri = builder.build().encode().toUri();

        ResponseEntity<JSONObject> resp = getRestTemplate().getForEntity(uri, JSONObject.class);
        JSONObject jsonObject = resp.getBody();

        String access_token = jsonObject.getString("access_token");
        return access_token;
    }
}
